package org.upfrost.mapping;

import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;

import org.upfrost.Mapper;
import org.upfrost.util.Pair;



/**
 * Manages the mapping between a class and the column number in a resultset, 
 * using the sql table name associated to the class.
 * It roughly maps CLASS.PROPERTY to TABLENAME.COLUMN.
 * 
 * @author Rodrigo Reyes
 */
public class MetaMapManager 
{
	// In the generics mess below:
	// - the Class is, well, the class being mapped
	// - the String is a property name from this class
	// - the Integer is the column number where the data from this property shall be fetched
	//
	private LinkedList<Pair<Class,HashMap<String,Integer>>> m_cache = new LinkedList<Pair<Class,HashMap<String,Integer>>>();

	public MetaMapManager(Mapper mapper, ResultSetMetaData meta) throws SQLException
	{
		for (int i=1; i<meta.getColumnCount()+1; i++)
		{
			String table = meta.getTableName(i);
			ClassProxy proxy = mapper.getClassProxy(table);
			if (proxy != null)
			{
				Pair<Class,HashMap<String,Integer>> p = findEntry(proxy.getMappedClass());
				if (p == null)
				{
					p = new Pair<Class,HashMap<String,Integer>>(proxy.getMappedClass(), new HashMap<String,Integer>());
					m_cache.add(p);
				}

				p.getSecond().put(meta.getColumnName(i).toLowerCase(), i);
			}
		}
	}

	private Pair<Class,HashMap<String,Integer>> findEntry(Class clazz)
	{
		for (Pair<Class,HashMap<String,Integer>>p: m_cache)
		{
			if (p.getFirst().equals(clazz))
				return p;
		}
		return null;
	}

	/**
	 * Return the column number associated to a class and an sql column name
	 * @param c
	 * @param sqlName
	 * @return
	 */
	public Integer getColumn(Class c, String sqlName)
	{
		Pair<Class,HashMap<String,Integer>> cacheEntry = findEntry(c);
		if (cacheEntry != null)
		{
			return cacheEntry.getSecond().get(sqlName.toLowerCase());
		}
		return null;
	}

}
